using Lzfy_His_Service.Models;
using Lzfy_His_Service.Repositories;
using System.Text.RegularExpressions;

namespace Lzfy_His_Service.Services
{
    /// <summary>
    /// 银行信息服务实现
    /// </summary>
    public class BankInfoService : IBankInfoService
    {
        private readonly IBankInfoRepository _bankInfoRepository;
        private readonly ILogger<BankInfoService> _logger;

        public BankInfoService(IBankInfoRepository bankInfoRepository, ILogger<BankInfoService> logger)
        {
            _bankInfoRepository = bankInfoRepository;
            _logger = logger;
        }

        /// <summary>
        /// 获取银行信息列表（分页）
        /// </summary>
        public async Task<PagedResponse<BankInfoResponse>> GetBankInfoListAsync(BankInfoQueryRequest request)
        {
            try
            {
                var (banks, totalCount) = await _bankInfoRepository.GetBankInfoListAsync(
                    request.Keyword, 
                    request.IsCustomOnly, 
                    request.IsActiveOnly, 
                    request.PageIndex, 
                    request.PageSize);

                var bankResponses = banks.Select(MapToBankInfoResponse).ToList();

                return new PagedResponse<BankInfoResponse>
                {
                    Data = bankResponses,
                    TotalCount = totalCount,
                    PageIndex = request.PageIndex,
                    PageSize = request.PageSize
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取银行信息列表失败");
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取银行信息详情
        /// </summary>
        public async Task<BankInfoResponse?> GetBankInfoByIdAsync(int id)
        {
            try
            {
                var bank = await _bankInfoRepository.GetBankInfoByIdAsync(id);
                return bank != null ? MapToBankInfoResponse(bank) : null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取银行信息详情失败，ID: {BankId}", id);
                throw;
            }
        }

        /// <summary>
        /// 创建银行信息
        /// </summary>
        public async Task<(bool success, string message, int? bankId)> CreateBankInfoAsync(BankInfoCreateRequest request, string? createdBy = null)
        {
            try
            {
                // 验证请求数据
                var validationResult = await ValidateCreateRequestAsync(request);
                if (!validationResult.isValid)
                {
                    return (false, validationResult.message, null);
                }

                // 转换为实体
                var bankInfo = MapToBankInfo(request, createdBy);

                // 创建银行信息
                var bankId = await _bankInfoRepository.CreateBankInfoAsync(bankInfo);

                _logger.LogInformation("银行信息创建成功，ID: {BankId}, 名称: {BankName}", bankId, request.StandardName);
                return (true, "银行信息创建成功", bankId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建银行信息失败，名称: {BankName}", request.StandardName);
                return (false, "创建银行信息失败：" + ex.Message, null);

            }
        }

        /// <summary>
        /// 更新银行信息
        /// </summary>
        public async Task<(bool success, string message)> UpdateBankInfoAsync(int id, BankInfoUpdateRequest request, string? updatedBy = null)
        {
            try
            {
                // 检查银行是否存在
                var existingBank = await _bankInfoRepository.GetBankInfoByIdAsync(id);
                if (existingBank == null)
                {
                    return (false, "银行信息不存在");
                }

                // 验证请求数据
                var validationResult = await ValidateUpdateRequestAsync(id, request);
                if (!validationResult.isValid)
                {
                    return (false, validationResult.message);
                }

                // 更新银行信息
                existingBank.StandardName = request.StandardName;
                existingBank.ShortName = request.ShortName;
                existingBank.EnglishName = request.EnglishName;
                existingBank.BankCode = request.BankCode;
                existingBank.CardLengthRule = request.CardLengthRule;
                existingBank.IsActive = request.IsActive;
                existingBank.SupportedCardTypes = request.SupportedCardTypes;
                existingBank.Description = request.Description;
                existingBank.Remark = request.Remark;
                existingBank.UpdatedAt = DateTime.Now;
                existingBank.UpdatedBy = updatedBy;

                var result = await _bankInfoRepository.UpdateBankInfoAsync(existingBank);

                if (result)
                {
                    _logger.LogInformation("银行信息更新成功，ID: {BankId}, 名称: {BankName}", id, request.StandardName);
                    return (true, "银行信息更新成功");
                }
                else
                {
                    return (false, "银行信息更新失败");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新银行信息失败，ID: {BankId}", id);
                return (false, "更新银行信息失败：" + ex.Message);
            }
        }

        /// <summary>
        /// 删除银行信息
        /// </summary>
        public async Task<(bool success, string message)> DeleteBankInfoAsync(int id, string? deletedBy = null)
        {
            try
            {
                // 检查银行是否存在
                var existingBank = await _bankInfoRepository.GetBankInfoByIdAsync(id);
                if (existingBank == null)
                {
                    return (false, "银行信息不存在");
                }

                var result = await _bankInfoRepository.DeleteBankInfoAsync(id);

                if (result)
                {
                    // 记录删除日志
                    await _bankInfoRepository.LogChangeAsync(new BankInfoChangeLog
                    {
                        BankId = id,
                        ChangeType = "DELETE",
                        FieldName = "IsActive",
                        OldValue = "True",
                        NewValue = "False",
                        CreatedAt = DateTime.Now,
                CreatedBy = deletedBy
                    });

                    _logger.LogInformation("银行信息删除成功，ID: {BankId}", id);
                    return (true, "银行信息删除成功");
                }
                else
                {
                    return (false, "银行信息删除失败");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除银行信息失败，ID: {BankId}", id);
                return (false, "删除银行信息失败：" + ex.Message);
            }
        }

        /// <summary>
        /// 搜索银行信息
        /// </summary>
        public async Task<List<BankSearchResponse>> SearchBankInfoAsync(string keyword, int limit = 10)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(keyword))
                {
                    return new List<BankSearchResponse>();
                }

                var banks = await _bankInfoRepository.SearchBankInfoAsync(keyword, limit);
                return banks.Select(bank => new BankSearchResponse
                {
                    Id = bank.Id,
                    Name = bank.StandardName,
                    ShortName = bank.ShortName,
                    EnglishName = bank.EnglishName,
                    IsCustom = bank.IsCustom
                }).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "搜索银行信息失败，关键词: {Keyword}", keyword);
                throw;
            }
        }

        /// <summary>
        /// 验证银行卡信息
        /// </summary>
        public async Task<BankCardValidationResponse> ValidateBankCardAsync(BankCardValidationRequest request)
        {
            try
            {
                var response = new BankCardValidationResponse
                {
                    IsValid = false,
                    CardNumberValid = false,
                    BankNameValid = false,
                    BankMatch = false,
                    Errors = new List<string>()
                };

                // 基础验证
                if (string.IsNullOrWhiteSpace(request.CardNumber))
                {
                    response.Errors.Add("银行卡号不能为空");
                    return response;
                }

                if (string.IsNullOrWhiteSpace(request.BankName))
                {
                    response.Errors.Add("银行名称不能为空");
                    return response;
                }

                // 银行卡号格式验证
                var cardNumber = request.CardNumber.Replace(" ", "").Replace("-", "");
                if (!Regex.IsMatch(cardNumber, @"^\d{13,19}$"))
                {
                    response.Errors.Add("银行卡号格式不正确，应为13-19位数");
                    return response;
                }

                response.CardNumberValid = true;

                // Luhn算法验证
                if (!ValidateLuhnAlgorithm(cardNumber))
                {
                    response.Errors.Add("银行卡号校验失败（Luhn算法）");
                    response.CardNumberValid = false;
                }

                // 银行名称标准化
                var standardizedBankName = StandardizeBankName(request.BankName);
                response.StandardizedBankName = standardizedBankName;

                // 根据BIN码查找银行
                var binCode = cardNumber.Substring(0, Math.Min(6, cardNumber.Length));
                var bankByBin = await _bankInfoRepository.GetBankInfoByBinCodeAsync(binCode);

                // 根据银行名称查找银行
                var bankByName = await _bankInfoRepository.GetBankInfoByStandardNameAsync(standardizedBankName) ??
                                await _bankInfoRepository.GetBankInfoByAliasAsync(standardizedBankName);

                if (bankByName != null)
                {
                    response.BankNameValid = true;
                    response.DetectedBank = bankByName.StandardName;

                    // 检查银行匹配
                    if (bankByBin != null && bankByBin.Id == bankByName.Id)
                    {
                        response.BankMatch = true;
                        response.IsValid = response.CardNumberValid && response.BankNameValid && response.BankMatch;
                    }
                    else if (bankByBin != null)
                    {
                        response.Errors.Add($"银行卡号归属银行({bankByBin.StandardName})与输入的银行名称({bankByName.StandardName})不匹配");
                    }
                    else
                    {
                        // 没有找到对应的BIN码，但银行名称有效
                        response.BankMatch = true;
                        response.IsValid = response.CardNumberValid && response.BankNameValid;
                        response.Errors.Add("未找到对应的BIN码信息，请确认银行卡号是否正确");
                    }
                }
                else
                {
                    response.Errors.Add("未找到对应的银行信息，请检查银行名称是否正确");
                    if (bankByBin != null)
                    {
                        response.DetectedBank = bankByBin.StandardName;
                        response.Errors.Add($"根据卡号检测到银行：{bankByBin.StandardName}");
                    }
                }

                return response;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证银行卡信息失败");
                return new BankCardValidationResponse
                {
                    IsValid = false,
                    Errors = new List<string> { "验证过程中发生错误：" + ex.Message }
                };
            }
        }

        /// <summary>
        /// 获取所有启用的银行列表
        /// </summary>
        public async Task<List<BankSearchResponse>> GetAllActiveBanksAsync()
        {
            try
            {
                var banks = await _bankInfoRepository.GetAllActiveBanksAsync();
                return banks.Select(bank => new BankSearchResponse
                {
                    Id = bank.Id,
                    Name = bank.StandardName,
                    ShortName = bank.ShortName,
                    EnglishName = bank.EnglishName,
                    IsCustom = bank.IsCustom
                }).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取所有启用银行列表失败");
                throw;
            }
        }

        /// <summary>
        /// 更新银行BIN码映射
        /// </summary>
        public async Task<(bool success, string message)> UpdateBankBinMappingsAsync(int bankId, List<string> binCodes, string? updatedBy = null)
        {
            try
            {
                // 验证BIN码格式
                var invalidBinCodes = binCodes.Where(bin => !Regex.IsMatch(bin, @"^\d{4,6}$")).ToList();
                if (invalidBinCodes.Any())
                {
                    return (false, $"BIN码格式不正确：{string.Join(", ", invalidBinCodes)}");
                }

                // 检查BIN码是否已被其他银行使用
                foreach (var binCode in binCodes)
                {
                    var exists = await _bankInfoRepository.IsBinCodeExistsAsync(binCode, bankId);
                    if (exists)
                    {
                        return (false, $"BIN码 {binCode} 已被其他银行使用");
                    }
                }

                var result = await _bankInfoRepository.UpdateBankBinMappingsAsync(bankId, binCodes, updatedBy);

                if (result)
                {
                    // 记录变更日志
                    await _bankInfoRepository.LogChangeAsync(new BankInfoChangeLog
                    {
                        BankId = bankId,
                        ChangeType = "UPDATE",
                        FieldName = "BinMappings",
                        NewValue = string.Join(", ", binCodes),
                        CreatedAt = DateTime.Now,
                CreatedBy = updatedBy
                    });

                    return (true, "BIN码映射更新成功");
                }
                else
                {
                    return (false, "BIN码映射更新失败");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新银行BIN码映射失败，银行ID: {BankId}", bankId);
                return (false, "更新BIN码映射失败：" + ex.Message);
            }
        }

        /// <summary>
        /// 更新银行别名
        /// </summary>
        public async Task<(bool success, string message)> UpdateBankAliasesAsync(int bankId, List<BankAliasRequest> aliases, string? updatedBy = null)
        {
            try
            {
                // 检查别名是否已被其他银行使用
                foreach (var alias in aliases)
                {
                    var exists = await _bankInfoRepository.IsAliasExistsAsync(alias.AliasName, bankId);
                    if (exists)
                    {
                        return (false, $"别名 {alias.AliasName} 已被其他银行使用");
                    }
                }

                var result = await _bankInfoRepository.UpdateBankAliasesAsync(bankId, aliases, updatedBy);

                if (result)
                {
                    // 记录变更日志
                    await _bankInfoRepository.LogChangeAsync(new BankInfoChangeLog
                    {
                        BankId = bankId,
                        ChangeType = "UPDATE",
                        FieldName = "Aliases",
                        NewValue = string.Join(", ", aliases.Select(a => $"{a.AliasName}({a.AliasType})")),
                        CreatedAt = DateTime.Now,
                CreatedBy = updatedBy
                    });

                    return (true, "银行别名更新成功");
                }
                else
                {
                    return (false, "银行别名更新失败");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新银行别名失败，银行ID: {BankId}", bankId);
                return (false, "更新银行别名失败：" + ex.Message);
            }
        }

        /// <summary>
        /// 获取银行变更日志
        /// </summary>
        public async Task<PagedResponse<BankInfoChangeLog>> GetChangeLogsAsync(int? bankId = null, int pageIndex = 1, int pageSize = 20)
        {
            try
            {
                var (logs, totalCount) = await _bankInfoRepository.GetChangeLogsAsync(bankId, pageIndex, pageSize);

                return new PagedResponse<BankInfoChangeLog>
                {
                    Data = logs,
                    TotalCount = totalCount,
                    PageIndex = pageIndex,
                    PageSize = pageSize
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取银行变更日志失败");
                throw;
            }
        }

        /// <summary>
        /// 导出银行信息数据
        /// </summary>
        public async Task<List<BankInfoResponse>> ExportBankInfoAsync()
        {
            try
            {
                var banks = await _bankInfoRepository.GetAllActiveBanksAsync();
                var result = new List<BankInfoResponse>();

                foreach (var bank in banks)
                {
                    var bankWithDetails = await _bankInfoRepository.GetBankInfoByIdAsync(bank.Id);
                    if (bankWithDetails != null)
                    {
                        result.Add(MapToBankInfoResponse(bankWithDetails));
                    }
                }

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出银行信息数据失败");
                throw;
            }
        }

        /// <summary>
        /// 导入银行信息数据
        /// </summary>
        public async Task<(bool success, string message, int successCount, int failCount)> ImportBankInfoAsync(
            List<BankInfoCreateRequest> bankInfoList, string? importedBy = null)
        {
            var successCount = 0;
            var failCount = 0;
            var errors = new List<string>();

            try
            {
                foreach (var bankInfo in bankInfoList)
                {
                    try
                    {
                        var result = await CreateBankInfoAsync(bankInfo, importedBy);
                        if (result.success)
                        {
                            successCount++;
                        }
                        else
                        {
                            failCount++;
                            errors.Add($"银行 {bankInfo.StandardName}: {result.message}");
                        }
                    }
                    catch (Exception ex)
                    {
                        failCount++;
                        errors.Add($"银行 {bankInfo.StandardName}: {ex.Message}");
                    }
                }

                var message = $"导入完成，成功 {successCount}，失败 {failCount}";
                if (errors.Any())
                {
                    message += $"\n错误详情：\n{string.Join("\n", errors.Take(10))}";
                    if (errors.Count > 10)
                    {
                        message += $"\n...还有 {errors.Count - 10} 个错误";
                    }
                }

                return (failCount == 0, message, successCount, failCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导入银行信息数据失败");
                return (false, "导入过程中发生错误：" + ex.Message, successCount, failCount);
            }
        }

        #region 私有方法

        /// <summary>
        /// 验证创建请求
        /// </summary>
        private async Task<(bool isValid, string message)> ValidateCreateRequestAsync(BankInfoCreateRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.StandardName))
            {
                return (false, "银行标准名称不能为空");
            }

            if (await _bankInfoRepository.IsBankNameExistsAsync(request.StandardName))
            {
                return (false, "银行名称已存在");
            }

            // 验证卡号长度规则格式
            if (!string.IsNullOrEmpty(request.CardLengthRule))
            {
                if (!System.Text.RegularExpressions.Regex.IsMatch(request.CardLengthRule, @"^\d{2}-\d{2}$"))
                {
                    return (false, "卡号长度规则格式不正确，应为'XX-XX'格式");
                }
            }

            // 验证BIN码
            if (request.BinCodes?.Any() == true)
            {
                foreach (var binCode in request.BinCodes)
                {
                    if (!Regex.IsMatch(binCode, @"^\d{4,6}$"))
                    {
                        return (false, $"BIN码格式不正确：{binCode}");
                    }

                    if (await _bankInfoRepository.IsBinCodeExistsAsync(binCode))
                    {
                        return (false, $"BIN码已存在：{binCode}");
                    }
                }
            }

            // 验证别名
            if (request.Aliases?.Any() == true)
            {
                foreach (var alias in request.Aliases)
                {
                    if (string.IsNullOrWhiteSpace(alias.AliasName))
                    {
                        return (false, "别名不能为空");
                    }

                    if (await _bankInfoRepository.IsAliasExistsAsync(alias.AliasName))
                    {
                        return (false, $"别名已存在：{alias.AliasName}");
                    }
                }
            }

            return (true, string.Empty);
        }

        /// <summary>
        /// 验证更新请求
        /// </summary>
        private async Task<(bool isValid, string message)> ValidateUpdateRequestAsync(int id, BankInfoUpdateRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.StandardName))
            {
                return (false, "银行标准名称不能为空");
            }

            if (await _bankInfoRepository.IsBankNameExistsAsync(request.StandardName, id))
            {
                return (false, "银行名称已存在");
            }

            // 验证卡号长度规则格式
            if (!string.IsNullOrEmpty(request.CardLengthRule))
            {
                if (!System.Text.RegularExpressions.Regex.IsMatch(request.CardLengthRule, @"^\d{2}-\d{2}$"))
                {
                    return (false, "卡号长度规则格式不正确，应为'XX-XX'格式");
                }
            }

            return (true, string.Empty);
        }

        /// <summary>
        /// 映射到银行信息实体
        /// </summary>
        private static BankInfo MapToBankInfo(BankInfoCreateRequest request, string? createdBy)
        {
            var bankInfo = new BankInfo
            {
                StandardName = request.StandardName,
                ShortName = request.ShortName,
                EnglishName = request.EnglishName,
                BankCode = request.BankCode,
                CardLengthRule = request.CardLengthRule,
                IsCustom = true, // 通过API创建的都标记为自定义
                IsActive = request.IsActive,
                SupportedCardTypes = request.SupportedCardTypes ?? "debit,credit",
                Description = request.Description,
                Remark = request.Remark,
                CreatedAt = DateTime.Now,
                CreatedBy = createdBy
            };

            // 添加BIN码映射
            if (request.BinCodes?.Any() == true)
            {
                bankInfo.BinMappings = request.BinCodes!.Select(bin => new BankBinMapping
                {
                    BinCode = bin,
                    IsActive = true,
                    CreatedAt = DateTime.Now,
                    CreatedBy = createdBy
                }).ToList();
            }

            // 添加别名
            if (request.Aliases?.Any() == true)
            {
                bankInfo.NameAliases = request.Aliases.Select(alias => new BankNameAlias
                {
                    AliasName = alias.AliasName,
                    AliasType = alias.AliasType ?? "common",
                    IsActive = true,
                    CreatedAt = DateTime.Now,
                    CreatedBy = createdBy
                }).ToList();
            }

            return bankInfo;
        }

        /// <summary>
        /// 映射到银行信息响应
        /// </summary>
        private static BankInfoResponse MapToBankInfoResponse(BankInfo bank)
        {
            // 解析卡号长度规则，例如"16-19" -> MinCardLength=16, MaxCardLength=19
            var (minLength, maxLength) = ParseCardLengthRule(bank.CardLengthRule);
            
            return new BankInfoResponse
            {
                Id = bank.Id,
                StandardName = bank.StandardName,
                ShortName = bank.ShortName,
                EnglishName = bank.EnglishName,
                BankCode = bank.BankCode,
                CardLengthRule = bank.CardLengthRule,
                MinCardLength = minLength,
                MaxCardLength = maxLength,
                IsActive = bank.IsActive,
                IsCustom = bank.IsCustom,
                SupportedCardTypes = bank.SupportedCardTypes,
                Description = bank.Description,
                CreatedAt = bank.CreatedAt,
                UpdatedAt = bank.UpdatedAt,
                CreatedBy = bank.CreatedBy,
                UpdatedBy = bank.UpdatedBy,
                Remark = bank.Remark,
                BinCodes = bank.BinMappings?.Where(x => x.IsActive).Select(x => x.BinCode).ToList() ?? new List<string>(),
                Aliases = bank.NameAliases?.Where(x => x.IsActive).Select(x => new BankAliasResponse
                {
                    Id = x.Id,
                    AliasName = x.AliasName,
                    AliasType = x.AliasType,
                    IsActive = x.IsActive
                }).ToList() ?? new List<BankAliasResponse>()
            };
        }
        
        /// <summary>
        /// 解析卡号长度规则
        /// </summary>
        private static (int minLength, int maxLength) ParseCardLengthRule(string? cardLengthRule)
        {
            if (string.IsNullOrWhiteSpace(cardLengthRule))
                return (16, 19);
                
            // 匹配 "16-19" 或 "16-19" 格式
            var match = Regex.Match(cardLengthRule, @"(\d+)-(\d+)");
            if (match.Success)
            {
                if (int.TryParse(match.Groups[1].Value, out var min) && 
                    int.TryParse(match.Groups[2].Value, out var max))
                {
                    return (min, max);
                }
            }
            
            // 匹配单个数字，如 "16"
            var singleMatch = Regex.Match(cardLengthRule, @"(\d+)");
            if (singleMatch.Success && int.TryParse(singleMatch.Groups[1].Value, out var length))
            {
                return (length, length);
            }
            
            return (16, 19); // 默认值
        }

        /// <summary>
        /// Luhn算法验证
        /// </summary>
        private static bool ValidateLuhnAlgorithm(string cardNumber)
        {
            var sum = 0;
            var alternate = false;

            for (var i = cardNumber.Length - 1; i >= 0; i--)
            {
                var digit = int.Parse(cardNumber[i].ToString());

                if (alternate)
                {
                    digit *= 2;
                    if (digit > 9)
                    {
                        digit = digit % 10 + 1;
                    }
                }

                sum += digit;
                alternate = !alternate;
            }

            return sum % 10 == 0;
        }

        /// <summary>
        /// 银行名称标准化
        /// </summary>
        private static string StandardizeBankName(string bankName)
        {
            if (string.IsNullOrWhiteSpace(bankName))
                return string.Empty;

            // 移除常见的后缀
            var suffixes = new[] { "银行", "Bank", "有限公司", "股份有限公司", "Co.,Ltd.", "Ltd.", "Inc." };
            var standardized = bankName.Trim();

            foreach (var suffix in suffixes)
            {
                if (standardized.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
                {
                    standardized = standardized.Substring(0, standardized.Length - suffix.Length).Trim();
                }
            }

            // 移除空格和特殊字符
            standardized = Regex.Replace(standardized, @"[\s\-_]+", "");

            return standardized;
        }

        #endregion
    }
}
